﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Diagnostics;
using System.Data;

namespace WSPDocGenerator
{
	public class HtmlHelpGeneratorProvider : IHelpGenerator
	{
		StringBuilder sb;
		const string START_TABLE = "<TABLE BORDER=\"1\">";
		const string END_TABLE = "</TABLE>";
		DataTable dtTableFeatures;
		
		public HtmlHelpGeneratorProvider()
		{
			sb = new StringBuilder();
			dtTableFeatures = new DataTable();
		}

		internal string GetCSS()
		{
			return @"<style TYPE=""text/css""> 
				body
                {
				    font-family: Arial, Helvetica, sans-serif;
				    font-size: 10px;
				}
				h1  
                {
				    font-size: 30px;
				    color: #248dc6;
				}
				h2 
                {
				    font-size: 20px;
				    color: #333333;
				}
				h3 
                {
				    font-size: 16px;
				    color: #248dc6;	
				}
				h4 
                {
				    font-size: 13px;
				    color: #333333;	
				}
				table
				{
					border: solid 1px #708090;
					background-color: #f7f7f7;
					padding: 0px;
					font-family: Arial, Helvetica, sans-serif;
					font-size: 11px;
					border-spacing:collapse;
					border-collapse: collapse;
					color: #7a7a7a;
				}
				th
				{
					background-color: #B3BDB9;
					padding-left: 10px;
					padding-right: 10px;
				}
				tD
				{
					padding-left: 3px;
					padding-right: 3px;
				}
				th strong
				{
				    color:#fff;
				}
				strong
                {
					color: #333333;
					font-size: 12px;
				}
				</style>";
		}

		public string Write()
		{
			string html = string.Format("<hmtl><head>{0}</head><body>{1}</body></html>",
				this.GetCSS(),
				sb.ToString());
			
			//Reset variables 
			sb = new StringBuilder();
			dtTableFeatures = new DataTable();
			
			return html;
		}

		public string Extension
		{
			get { return "html"; }
		}

		public void WSP(string name)
		{
			sb.AppendFormat("<H1>WSP: {0}.wsp</H1>", name);
		}

		public void Manifest(System.Xml.XmlDocument xmlDoc)
		{

			XmlNode solution = xmlDoc.DocumentElement;
			
			XmlNodeList nodes = solution.ChildNodes;
			foreach (XmlNode node in nodes)
			{
				if (node.HasChildNodes || (node.Attributes != null && node.Attributes.Count > 0))
				{
					// Assemblies
					sb.AppendFormat("<H2>{0}</H2>", node.Name);
					DataTable dtTable = new DataTable();
					foreach (XmlNode subNode in node.ChildNodes)
					{
						// Assembly
						if (subNode.Attributes != null)
						{
							DataRow row = dtTable.NewRow();
							foreach (XmlAttribute attrib in subNode.Attributes)
							{
								//Attributes
								TableAddNewRow(dtTable, row, attrib.Name, attrib.Value);
							}
							dtTable.Rows.Add(row);
						}
					}

					// Render
					RenderTable(dtTable);
				}
			}

			string html = sb.ToString();
		}

		private void TableAddNewRow(DataTable dtTable, DataRow row, string column, string value)
		{
			//DataRow row = dtTable.NewRow();
			if (!dtTable.Columns.Contains(column))
			{
				dtTable.Columns.Add(column);
				if (string.Compare(column, "location", true) == 0)
					dtTable.Columns.Add("Description");
			}
			row[column] = value;
		}

		public void EnumFeatures(System.Xml.XmlDocument xmlDoc, string title)
		{
			XmlNode feature = xmlDoc.DocumentElement;

			//RenderAttributes(feature);
			if (feature.Attributes != null)
			{
				if (feature.Attributes.Count > 0)
				{
					DataRow row = dtTableFeatures.NewRow();
					foreach (XmlAttribute attrib in feature.Attributes)
					{
						//Attributes
						TableAddNewRow(dtTableFeatures, row, attrib.Name, attrib.Value);
					}
					dtTableFeatures.Rows.Add(row);
				}
			}
		}

		public void Feature(System.Xml.XmlDocument xmlDoc, string title)
		{
			XmlNode feature = xmlDoc.DocumentElement;

			if (feature.ChildNodes.Count > 0)
			{
				sb.AppendFormat("<H3>Feature: {0}</H3>", title);
				//RenderAttributes(feature);

				XmlNodeList nodes = feature.ChildNodes;
				foreach (XmlNode node in nodes)
				{
					if (node.HasChildNodes || (node.Attributes != null && node.Attributes.Count > 0))
					{
						// Assemblies
						sb.AppendFormat("<H4>{0}</H4>", node.Name);
						RenderAttributes(node);

						DataTable dtTable = new DataTable();
						foreach (XmlNode subNode in node.ChildNodes)
						{
							// Assembly
							if (subNode.Attributes != null)
							{
								DataRow row = dtTable.NewRow();
								foreach (XmlAttribute attrib in subNode.Attributes)
								{
									//Attributes
									TableAddNewRow(dtTable, row, attrib.Name, attrib.Value);
								}
								dtTable.Rows.Add(row);
							}
						}

						// Render
						RenderTable(dtTable);
					}
				}
			}

			string html = sb.ToString();
		}

		public void Element(System.Xml.XmlDocument xmlDoc, string title)
		{
			XmlNode element = xmlDoc.DocumentElement;

			sb.AppendFormat("<H3>Element: {0}</H3>", title);
			RenderAttributes(element);

			XmlNodeList nodes = element.ChildNodes;
			foreach (XmlNode node in nodes)
			{
				if (node.NodeType != XmlNodeType.Comment && (node.HasChildNodes || node.Attributes.Count > 0))
				{
					// Assemblies
					sb.AppendFormat("<H4>{0}</H4>", node.Name);
					bool hasAttributes = RenderAttributes(node);

					if (hasAttributes)
						sb.Append("<BR/>");

					DataTable dtTable = new DataTable();
					foreach (XmlNode subNode in node.ChildNodes)
					{
						// Assembly
						if (subNode.Attributes != null)
						{
							DataRow row = dtTable.NewRow();
							foreach (XmlAttribute attrib in subNode.Attributes)
							{
								//Attributes
								TableAddNewRow(dtTable, row, attrib.Name, attrib.Value);
							}
							dtTable.Rows.Add(row);
						}
					}

					// Render
					RenderTable(dtTable);
				}
			}

			string html = sb.ToString();
		}

		public void RenderFeature()
		{
			if (dtTableFeatures.Rows.Count > 0)
			{ 
				sb.AppendFormat("<H2>Features</H2>");
				OrderFeatureTableColumns(dtTableFeatures);
				RenderTable(dtTableFeatures);
			}
		}

		private void RenderTable(DataTable dtTable)
		{
			sb.AppendFormat(START_TABLE);
			sb.AppendFormat("<TR>");
			foreach (DataColumn col in dtTable.Columns)
			{
				if (!col.ColumnName.Contains("xmlns"))
					sb.AppendFormat("<TH><strong><center>{0}</center></strong></TH>", col.ColumnName);
			}
			sb.AppendFormat("</TR>");
			foreach (DataRow row in dtTable.Rows)
			{
				sb.AppendFormat("<TR>");
				foreach (DataColumn col in dtTable.Columns)
				{
					if (!col.ColumnName.Contains("xmlns"))
						sb.AppendFormat("<TD>{0}</TD>", string.IsNullOrWhiteSpace(row[col.ColumnName].ToString()) ? "&nbsp;" : row[col.ColumnName]);
				}
				sb.AppendFormat("</TR>");
			}
			sb.AppendFormat(END_TABLE);
		}

		private void OrderFeatureTableColumns(DataTable dtTable)
		{
			TableColumnSetOrdinal(dtTable, "Title", 0);
			TableColumnSetOrdinal(dtTable, "Id", 1);
			TableColumnSetOrdinal(dtTable, "Description", 2);
			TableColumnSetOrdinal(dtTable, "Scope", 3);
			TableColumnSetOrdinal(dtTable, "Hidden", 4);
		}

		private void TableColumnSetOrdinal(DataTable dtTable, string column, int newOrdinal)
		{
			if (dtTable.Columns[column] != null)
				dtTable.Columns[column].SetOrdinal(newOrdinal);
		}


		private bool RenderAttributes(XmlNode node)
		{
			if (node.Attributes != null)
			{
				if (node.Attributes.Count > 0)
				{

					StringBuilder sbAttribs = new StringBuilder();
					bool hasAttribute = false;

					sbAttribs.AppendFormat(START_TABLE);
					sbAttribs.AppendFormat("<TR>");
					foreach (XmlAttribute att in node.Attributes)
					{
						if (!att.Name.Contains("xmlns"))
						{
							sbAttribs.AppendFormat("<TH><strong><center>{0}</center></strong></TH>", att.Name);
							hasAttribute = true;
						}
					}

					if (hasAttribute)
					{
						sbAttribs.AppendFormat("</TR>");
						sbAttribs.AppendFormat("<TR>");
						foreach (XmlAttribute att in node.Attributes)
						{
							if (!att.Name.Contains("xmlns"))
								sbAttribs.AppendFormat("<TD>{0}</TD>", string.IsNullOrWhiteSpace(att.Value) ? "&nbsp;" : att.Value);
						}
						sbAttribs.AppendFormat("</TR>");
						sbAttribs.AppendFormat(END_TABLE);

						sb.Append(sbAttribs.ToString());
						return true;
					}
					
				}
			}
			return false;
		}


	}
}
